package fjut.acm.coding.controller;

import fjut.acm.coding.component.judge.data.StatusType;
import fjut.acm.coding.config.interceptor.LoginRequired.LoginRequired;
import fjut.acm.coding.entity.ContestInfoPO;
import fjut.acm.coding.entity.UserContestProblemSloved;
import fjut.acm.coding.entity.enums.CodeLanguage;
import fjut.acm.coding.entity.result.ResultCode;
import fjut.acm.coding.entity.result.ResultJson;
import fjut.acm.coding.entity.vo.ContestListVO;
import fjut.acm.coding.entity.vo.ContestProblemVO;
import fjut.acm.coding.entity.vo.ContestRankVO;
import fjut.acm.coding.entity.vo.UserContestProblemSlovedVO;
import fjut.acm.coding.service.*;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import java.util.*;

@RestController
@CrossOrigin
@RequestMapping("/contest")
public class ContestController {
    @Resource
    ContestInfoService contestInfoService;

    @Resource
    ContestProblemService contestProblemService;

    @Resource
    UserContestProblemSlovedService userContestProblemSlovedService;

    @Resource
    JudgeStatusService judgeStatusService;

    @Resource
    ViewJudgeStatusService viewJudgeStatusService;

    @GetMapping("/list")
    public ResultJson getContestList(@RequestParam("kind") Integer kind,
                                     @RequestParam("pageNum") Integer pageNum,
                                     @RequestParam("pageSize") Integer pageSize,
                                     @RequestParam(value = "searchName", required = false) String searchName,
                                     @RequestParam(value = "searchPermission", required = false) Integer searchPermission,
                                     @RequestParam(value = "searchStatus", required = false) Integer searchStatus) {
        ResultJson resultJson = new ResultJson(ResultCode.REQUIRED_SUCCESS);
        if (StringUtils.isEmpty(searchName)) {
            searchName = null;
        } else {
            searchName = "%" + searchName + "%";
        }
        List<ContestListVO> contestListVOS = contestInfoService.pagesByConditions(kind, searchName, searchPermission, searchStatus, pageNum, pageSize);
        Integer count = contestInfoService.selectCountByConditions(kind, searchName, searchPermission, searchStatus);
        resultJson.addInfo(contestListVOS);
        resultJson.addInfo(count);
        return resultJson;
    }

    @LoginRequired
    @GetMapping("/info")
    public ResultJson getContestInfo(@RequestParam("contestId") Integer contestId,
                                     @RequestParam(value = "username", required = false) String username) {
        ResultJson resultJson = new ResultJson();
        ContestInfoPO contestInfoPO = contestInfoService.selectByContestId(contestId);
        resultJson.addInfo(contestInfoPO);
        return resultJson;
    }

    @LoginRequired
    @GetMapping("/problem/list")
    public ResultJson getContestProblemList(@RequestParam("contestId") Integer contestId) {
        ResultJson resultJson = new ResultJson();
        List<ContestProblemVO> contestProblemPOS = contestProblemService.selectByContestId(contestId);
        resultJson.addInfo(contestProblemPOS);
        return resultJson;
    }

    @LoginRequired
    @GetMapping("/status/list")
    public ResultJson getContestStatusList(@RequestParam("contestId") Integer contestId,
                                           @RequestParam("pageNum") Integer pageNum,
                                           @RequestParam("pageSize") Integer pageSize,
                                           @RequestParam(value = "nick", required = false) String nick,
                                           @RequestParam(value = "problemId", required = false) Integer problemId,
                                           @RequestParam(value = "result", required = false) String resultStr,
                                           @RequestParam(value = "language", required = false) String languageStr) {
        ResultJson resultJson = new ResultJson();
        if (null == pageNum) {
            pageNum = 1;
        }
        if (null == pageSize) {
            pageSize = 30;
        }
        if (!StringUtils.isEmpty(nick)) {
            nick = "%" + nick + "%";
        } else {
            nick = null;
        }
        Integer result = null;
        Integer language = null;
        if (StringUtils.isEmpty(problemId)) {
            problemId = null;
        }
        if (!StringUtils.isEmpty(resultStr)) {
            result = StatusType.getCodeByName(resultStr);
        }
        if (!StringUtils.isEmpty(languageStr)) {
            language = CodeLanguage.getCodeByName(languageStr);
        }
        // FIXME: 这里需要修改
        //List<JudgeStatus> judgeStatuses = judgeStatusService.pagesByConditions(pageNum, pageSize, contestId, nick, problemId, result, language);
        //Integer length = judgeStatusService.selectCountByConditions(contestId, nick, problemId, result, language);
        //resultJsonVO.setStatus(ResultJsonCode.REQUIRED_SUCCESS);
        //resultJsonVO.addInfo(judgeStatuses);
        //resultJsonVO.addInfo(length);
        return resultJson;
    }

    @RequestMapping("/rank")
    public ResultJson contestRank(@RequestParam("contestId")Integer contestId){
        ResultJson resultJson = new ResultJson();
        List<UserContestProblemSloved>  userContestProblemSloveds = userContestProblemSlovedService.selectByContestId(contestId);

        List<UserContestProblemSlovedVO> userContestProblemSlovedVOS = new ArrayList<>(userContestProblemSloveds.size());
        Map<String,ContestRankVO> map = new HashMap<>();
        for(UserContestProblemSloved item : userContestProblemSloveds){
            UserContestProblemSlovedVO vo = new UserContestProblemSlovedVO();
            vo.setIsSloved(item.getSloved());
            vo.setProblemId(item.getProblemId());
            vo.setUsername(item.getUsername());
            vo.setWrongNumber(item.getWrong());
            vo.setNickname(item.getNickName());
            userContestProblemSlovedVOS.add(vo);

            if(!map.containsKey(item.getUsername())){
                ContestRankVO temp = new ContestRankVO();
                temp.setAcnumber(0);
                temp.setWrongnumber(0);
                temp.setUsername(item.getUsername());
                temp.setNickname(item.getNickName());
                map.put(item.getUsername(),temp);
            }
            ContestRankVO temp = map.get(item.getUsername());
            if(item.getSloved() == 1){
                temp.setAcnumber(temp.getAcnumber()+1);
                temp.setWrongnumber(temp.getWrongnumber() + item.getWrong());
            }
        }

        List<ContestRankVO>  contestRankVOS = new ArrayList<>();
        for(String username : map.keySet()){
            contestRankVOS.add(map.get(username));
        }

        Collections.sort(contestRankVOS, new Comparator<ContestRankVO>(){
            public int compare(ContestRankVO o1, ContestRankVO o2) {
                //排序属性
                if(o1.getAcnumber() > o2.getAcnumber()){
                    return -1;
                }
                if(o1.getAcnumber() == o2.getAcnumber()){
                    if(o1.getWrongnumber()>o2.getWrongnumber()){
                        return 1;
                    }
                    if(o1.getWrongnumber()<o2.getWrongnumber()){
                        return -1;
                    }
                    return 0;
                }
                return 1;
            }
        });

        int i=0;
        for(ContestRankVO item : contestRankVOS){
            item.setRank(i++);
        }
        resultJson.addInfo(contestRankVOS);
        resultJson.addInfo(userContestProblemSlovedVOS);
        return resultJson;
    }
}
